/*
 * Copyright 2009 Jiwei Xu (http://www.xujiwei.com)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

provide("Objects.FigureObj");

FigureObj = Class({
    Initialize : function() {
        this.Position = { X : 0, Y : 0 };
        this.Handles = [];
        this.IsSelected = false;
        this.Bounds = this.CalcBounds();
        this.IsFill = false;
        this.LineWidth = 1;
        this.Alpha = 1.0;
        this.FillStyle = "white";
        this.StokeStyle = "black";
        this.Composite = "source-over";
    },

    AddHandle : function(pt, index) {
        index *= 1;
        if (isNaN(index)) {
            this.Handles[this.Handles.length] = {X:pt.X, Y:pt.Y};
        } else {
            this.Handles.splice(index, 0, {X:pt.X, Y:pt.Y});
        }
    },

    RemoveHandle : function(index) {
        index *= 1;
        if (index >= 0 && this.Handles[index]) {
            return this.Handles.splice(index, 1);
        }
    },

    SetStyles : function(ctx) {
        ctx.fillStyle = this.FillStyle;
        ctx.strokeStyle = this.StrokeStyle;
        ctx.lineWidth = this.LineWidth;
        ctx.globalAlpha = this.Alpha;
        ctx.globalCompositeOperation = this.Composite;
    },

    CalcBounds : function() {
        var h = this.Handles;
        if (h.length < 1) {
            h = [this.Position];
        }

        var top, bottom, left, right;
        top = bottom = h[0].Y;
        left = right = h[0].X;

        for (var i = 0; i < h.length; ++i) {
            var l = h[i];
            if (l.Y < top)    { top     = l.Y; }
            if (l.X > right)  { right   = l.X; }
            if (l.Y > bottom) { bottom  = l.Y; }
            if (l.X < left)   { left    = l.X; }
        }

        this.Bounds = {
            Top     : top,
            Right   : right,
            Bottom  : bottom,
            Left    : left,
            Width   : right - left,
            Height  : bottom - top
        };

        this.Position.X = this.Bounds.Left;
        this.Position.Y = this.Bounds.Top;

        return this.Bounds;
    },

    Draw : function(ctx) {
        throw new Error("You must implements 'Draw' method");
    },

    DrawHandles : function(ctx) {
        ctx.save();
        ctx.fillStyle = "black";
        ctx.globalAlpha = 1;
        ctx.beginPath();
        for (var i = 0; i < this.Handles.length; ++i) {
            var handle = this.Handles[i];
            ctx.fillRect(handle.X - 4, handle.Y - 4, 8, 8);
        }
        ctx.fill();
        ctx.restore();
    },

    Move : function(delta) {
        if (this.Position) {
            this.Position.X += delta.X;
            this.Position.Y += delta.Y;
        }

        for (var i = 0; i < this.Handles.length; ++i) {
            this.Handles[i].X += delta.X;
            this.Handles[i].Y += delta.Y;
        }

        this.CalcBounds();
    },

    MoveTo : function(pos) {
        var delta = {
            X : pos.X - this.Position.X,
            Y : pos.Y - this.Position.Y
        };

        this.Move(delta);
    },

    MoveHandle : function(index, delta) {
        if (this.Handles[index]) {
            this.Handles[index].X += delta.X;
            this.Handles[index].Y += delta.Y;
            this.CalcBounds();
        }
    },

    MoveHandleTo : function(index, pos) {
        if (this.Handles[index]) {
            var delta = {
                X : pos.X - this.Handles[index].X,
                Y : pos.Y - this.Handles[index].Y
            };
            this.MoveHandle(index, delta);
        }
    },

    HitTest : function(pt) {
        var bounds = this.CalcBounds();
        return pt.X >= bounds.Left && pt.X <= bounds.Right &&
            pt.Y >= bounds.Top  && pt.Y <= bounds.Bottom;
    },

    HitHandleTest : function(pt) {
        var h = this.Handles;
        //console.log("HitHandleTest: " + pt.X + ", " + pt.Y);
        for (var i = 0; i < h.length; ++i) {
            var l = h[i];
            //console.log(l);
            if (pt.X >= l.X-4 && pt.X <= l.X+4 &&
                pt.Y >= l.Y-4 && pt.Y <= l.Y+4) {
                return i;
            }
        }

        return -1;
    }
});